home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #1 / Ham Radio 2000.iso / ham2000 / tcp_ip / tnos / tnos100s / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-01-09  |  47.9 KB  |  2,109 lines

  1. /* Main-level network program:
  2.  * initialization
  3.  * keyboard processing
  4.  * generic user commands
  5.  *
  6.  * Copyright 1991 Phil Karn, KA9Q
  7.  * Mods by KO4KS
  8.  */
  9. #include <stdio.h>
  10. #include <time.h>
  11. #if    defined(__TURBOC__) && defined(MSDOS)
  12. #include <fcntl.h>
  13. #include <dos.h>
  14. #include <io.h>
  15. #include <conio.h>
  16. #include <ctype.h>
  17. #include <dir.h>
  18. #endif
  19. #include "global.h"
  20. #include "config.h"
  21. #ifdef    ANSIPROTO
  22. #include <stdarg.h>
  23. #endif
  24. #include "mbuf.h"
  25. #include "timer.h"
  26. #include "proc.h"
  27. #include "iface.h"
  28. #include "ip.h"
  29. #include "tcp.h"
  30. #include "udp.h"
  31. #include "ax25.h"
  32. #include "kiss.h"
  33. #include "enet.h"
  34. #include "netrom.h"
  35. #include "ftpcli.h"
  36. #include "telnet.h"
  37. #include "tty.h"
  38. #include "session.h"
  39. #include "hardware.h"
  40. #include "usock.h"
  41. #include "socket.h"
  42. #ifdef LZW
  43. #include "lzw.h"
  44. #endif
  45. #include "cmdparse.h"
  46. #include "commands.h"
  47. #include "daemon.h"
  48. #include "devparam.h"
  49. #include "domain.h"
  50. #include "files.h"
  51. #include "main.h"
  52. #include "mailbox.h"
  53. #include "remote.h"
  54. #include "trace.h"
  55. #include "mailutil.h"
  56. #include "smtp.h"
  57.  
  58. #ifdef XSPAWN
  59. #include "xspawn.h"
  60. #endif
  61.  
  62. extern struct cmds DFAR Cmds[],DFAR Startcmds[],DFAR Stopcmds[],Attab[];
  63. extern int SYSback, SYSfore;
  64. extern char vgaDesired;
  65. extern unsigned char SCREENlength;
  66.  
  67. extern short NextCmd;
  68. extern struct session *ScreenOwner;        /* Session currently displayed */
  69.  
  70. #if    (!defined(MSDOS) || defined(ESCAPE))    /* PC uses F-10 key always */
  71. static char Escape = 0x1d;    /* default escape character is ^] */
  72. #endif
  73.  
  74. #ifdef __TURBOC__
  75. int dofstat __ARGS((void));
  76. #endif
  77. char NoRead[] = "Can't read %s: %s\n";
  78. char Badhost[] = "Unknown host %s\n";
  79. char Badinterface[] = "Interface \"%s\" unknown\n";
  80. char Existingiface[] = "Interface %s already exists\n";
  81. char Nospace[] = "No space!!\n";    /* Generic malloc fail message */
  82. #ifdef ITT
  83. char Nosversion[] = "ITT Tactical MultiNet Gateway\n%s";
  84. char NosLoadInfo[] = "Load info: CS=0x%04x DS=0x%04x";
  85. char Prompt[] = "TMNG";
  86. #else
  87. #if defined(TNOS) && !defined(ITT)
  88. char readmeFile[] = "features.new";
  89. #endif
  90. extern char DFAR Tnosversion[];
  91. char Nosversion[] = "KA9Q NOS version %s\n";
  92. char NosLoadInfo[] = "TNOS load info: CS=0x%04x DS=0x%04x";
  93. char Prompt[] = "Net";
  94. #endif
  95. char Noperm[] = "Permission denied.\n";
  96. char Nosock[] = "Can't create socket\n";
  97. char FromSysop[] = "*** Msg from SYSOP: %s\n";
  98. char SysMessage[] = "System message";
  99. char *Hostname = NULLCHAR;
  100. char *Motd = NULLCHAR;            /* Message Of The Day */
  101. int Attended = TRUE;            /* default to attended mode */
  102. int ThirdParty = TRUE;            /* Allows 3rd party mail by default */
  103. int main_exit = FALSE;            /* from main program (flag) */
  104. int Mprunning = 0;        /* flag for other parts (domain) to signal
  105.                          * that we are fully configured running.
  106.                          */
  107. struct proc *Cmdpp;
  108. struct proc *Display;
  109. #ifdef    LZW
  110. int Lzwmode = LZWCOMPACT;
  111. int16 Lzwbits = LZWBITS;
  112. #endif
  113.  
  114. #ifdef TRACE
  115. int Tracesession = 1;
  116. struct session *Trace = NULLSESSION;
  117. #endif
  118.  
  119. static char PromptType;
  120.  
  121. static char *DumpAddr = NULL;        /* Memory dump pointer */
  122. static FILE *Logfp;
  123. time_t StartTime;        /* Time that NOS was started */
  124. static int Verbose;
  125. char *firstMsg;
  126. struct hist *Histry;    /* command recall stuff */
  127. int Histrysize;
  128. int Maxhistory = 10;
  129. #ifdef TNOS_68K
  130. extern int Initroot;
  131. extern int TNOS_68KAlarm;
  132. extern short UseCurses;
  133. #endif
  134.  
  135.  
  136. static void ctohex __ARGS((char *buf,int16 c));
  137. static void fmtline __ARGS((int16 addr,char *buf,int16 len));
  138. #ifndef TNOS_68K
  139. extern void VMSinit (), VMSterm();
  140. #endif
  141. extern void displayStatLine __ARGS((int offset));
  142. extern void statLineToggle (), statlog();
  143. extern void assign_filenames __ARGS((char *, int));
  144. static void logcmd __ARGS((char *));
  145. static void freehistory ();
  146.  
  147. #ifdef MSDOS
  148. char cpuid[]={
  149.  0x52,0x33,0xD2,0x9C,0x58,0x80,0xE4,0x0F,0x50,0x9D,0x9C,
  150.  0x58,0x80,0xE4,0xF0,0x80,0xFC,0xF0,0x74,0x12,0xFE,0xC2,
  151.  0x9C,0x58,0x80,0xCC,0xF0,0x50,0x9D,0x9C,0x58,0x80,0xE4,
  152.  0xF0,0x74,0x02,0xFE,0xC2,0xFE,0xC2,0x8B,0xC2,0x5A,0xCB},
  153.  *cpuname[]={"8088/8086/V20/V30","80286","80386/80486"};
  154. #endif
  155.  
  156.  
  157. void netPrompt ()
  158. {
  159. char *str;
  160.     switch (PromptType)    {
  161.         case 2:        str = Command->curdirs->dir;
  162.                 break;
  163.         case 1:        if (Hostname)    {
  164.                     str = Hostname;
  165.                     break;
  166.                 }    /* else, fall through */
  167.         default:    str = Prompt;
  168.     }
  169.     tprintf ("%s> ", str);
  170.     usflush(Command->output);
  171. }
  172.  
  173. int
  174. main(argc,argv)
  175. int argc;
  176. char *argv[];
  177. {
  178.     char *inbuf,*intmp;
  179.     FILE *fp;
  180.     struct daemon *tp;
  181.     struct mbuf *bp;
  182.     int i;
  183.     int c;
  184.     struct cur_dirs dirs;
  185. #ifdef MSDOS
  186.     int cpu,(DFAR *CpuId)()=(int (DFAR *)())cpuid;
  187. #endif
  188.  
  189. #ifdef XSPAWN
  190.         /* These vectors WILL be intercepted by NOS in COMMAND.ASM
  191.            Go ahead and tell XSPAWN to save their current state, now.
  192.            Vector 0x23 is also used by NOS, but is ALREADY being preserved
  193.            by the XSPAWN routines    */
  194.     addvect (8, CURRENT);
  195.     addvect (0x10, CURRENT);
  196.     addvect (0x13, CURRENT);
  197.     addvect (0x1b, CURRENT);
  198.     addvect (0x21, CURRENT);
  199.     addvect (0x24, CURRENT);
  200.     addvect (0x28, CURRENT);
  201. #endif
  202.     StartTime = time(&StartTime);            /* NOS Start_Up time */
  203.     randomize();
  204.  
  205.     while((c = getopt(argc,argv,"k:g:s:f:x:d:o:nbvec")) != EOF){
  206.         switch(c){
  207.  
  208. #ifdef TRACE
  209.         case 'n':    /* No session for tracing */
  210.             Tracesession = 0;
  211.             break;
  212. #endif
  213.         case 'k':    /* background color */
  214.             i= (getcolor (optarg) + 10);
  215.             if (i)
  216.                 SYSback = i;
  217.             break;
  218.         case 'g':    /* foreground color */
  219.             i = getcolor (optarg);
  220.             if (i)
  221.                 SYSfore = i;
  222.             break;
  223. #ifdef TNOS_68K
  224.         case 'c':    /* curses mode */
  225.             UseCurses = 1;
  226.             break;
  227. #endif
  228.             case 's':   /* Number of sockets */
  229.             Nusock = atoi(optarg);
  230.             break;
  231.         case 'f':   /* read a filename config file */
  232.             assign_filenames(optarg, 1);
  233.             break;
  234. #ifdef XSPAWN
  235.         case 'x':   /* Path for XSWAP temp file */
  236.             _swappath = strdup(optarg);
  237.             break;
  238. #endif
  239.         case 'd':    /* Root directory for various files */
  240.             initroot(optarg);
  241.             break;
  242. #ifdef    __TURBOC__
  243.         case 'b':    /* Use BIOS for screen output */
  244.             directvideo = 0;
  245.             break;
  246. #endif
  247.         case 'v':
  248.             Verbose = 1;
  249.             break;
  250. #ifndef TNOS_68K
  251.         case 'e':    /* EGA/VGA 43/50 mode desired */
  252.             vgaDesired = 1;
  253.             break;
  254. #endif
  255.         case 'o':    /* override number of interactive sessions */
  256.             Nsessions = atoi (optarg);
  257.             if (Nsessions < 5)
  258.                 Nsessions = 5;    /* but not less than 5 */
  259.             break;
  260.         }
  261.     }
  262. #if defined(TNOS) && !defined(TNOS_68K)
  263.     VMSinit ();
  264. #endif
  265. #ifdef TNOS_68K
  266.     if (!Initroot)
  267.         initroot ("/dd/nos");
  268.     oskinit();
  269. #ifdef TRACE
  270.     Tracesession = UseCurses;    /* no session trace if dumb terminal mode */
  271. #endif
  272. #endif
  273.     intmp = firstMsg;    /* we won't report an error here, if it occurs */
  274.     firstMsg = (char *) 0;
  275.     assign_filenames("config.nos", 0);    /* automatically look for users config */
  276.     if (firstMsg)
  277.         free (firstMsg);
  278.     firstMsg = intmp;
  279. #ifdef ITT
  280.     chdir ("/r0");
  281. #endif
  282.     kinit();
  283.     ipinit();
  284.     ioinit();
  285.     sockinit();
  286.     Cmdpp = mainproc("cmdintrp");
  287.  
  288.     Sessions = (struct session *)callocw(Nsessions,sizeof(struct session));
  289.     for (i = 0; i < Nsessions; i++)
  290.         Sessions[i].index = i;
  291. #ifdef TRACE
  292.     if(Tracesession)
  293.         Trace = newsession(NULLCHAR,TRACESESSION,0);
  294. #endif
  295.     ScreenOwner = Command = Lastcurr = newsession(NULLCHAR,COMMAND,0);/*"command int" not needed*/
  296.     /* Flow mode is set AFTER we've read the autoexec file !
  297.      * this keeps systems from locking up if the reboot is unattended - WG7J
  298.      */
  299. #ifndef TNOS_68K
  300.     Display = newproc("display",250,display,0,NULLCHAR,NULL,0);
  301. #else
  302.     Display = newproc("display",512,display,0,NULLCHAR,NULL,0);
  303. #endif
  304.     setscreens (0, 0, 1);
  305.     if (firstMsg)    {
  306.         tputs (firstMsg);
  307.         free (firstMsg);
  308.     }
  309. #if defined(TNOS) && !defined(ITT)
  310.     tprintf(Tnosversion);
  311. #else
  312.     tprintf(Nosversion,Version);
  313. #endif
  314. #ifndef ITT
  315.     tputs(Version2);
  316.     tputs("Copyright 1991 by Phil Karn (KA9Q) and contributors.\n");
  317. #else
  318.     tputs ("\n\n");
  319. #endif
  320. #ifdef MSDOS
  321.     cpu=(*CpuId)();
  322.     tprintf("Processor detected: %s\n",cpuname[cpu-1]);
  323. #endif
  324.     rflush();
  325.  
  326.     usercvt();
  327.     /* Start background Daemons */
  328.     for(tp=Daemons;;tp++){
  329.         if(tp->name == NULLCHAR)
  330.             break;
  331.         newproc(tp->name,tp->stksize,tp->fp,0,NULLCHAR,NULL,0);
  332.     }
  333.  
  334.     init_dirs(&dirs);
  335.     Command->curdirs=&dirs;
  336.  
  337. #if defined(TNOS) && !defined(ITT)
  338.     if(!access (readmeFile, 4))        {
  339.         int row;
  340.         char *args[2];
  341.         args[1] = readmeFile;
  342.         tprintf ("\nWould you like to view the '%s' file, containing information\non the new features for this version of TNOS?\n", readmeFile);
  343.             Command->ttystate.edit = Command->ttystate.echo = 0;
  344.                 row = keywait("Yes or No [y/n]? ",0);
  345.                 Command->ttystate.edit = Command->ttystate.echo = 1;
  346.                 if (row == 'Y' || row == 'y')
  347.                         doview (2, args, 0);
  348.                 tputc ('\n');
  349.         }
  350. #endif
  351.  
  352.     if(optind < argc){
  353.         /* Read startup file named on command line */
  354.         if((fp = fopen(argv[optind],READ_TEXT)) == NULLFILE)
  355.             tprintf(NoRead,argv[optind],sys_errlist[errno]);
  356.     } else {
  357.         /* Read default startup file named in files.c (autoexec.nos) */
  358.         if((fp = fopen(Startup,READ_TEXT)) == NULLFILE)
  359.             tprintf(NoRead,Startup,sys_errlist[errno]);
  360.     }
  361.     if(fp != NULLFILE){
  362.         inbuf = mallocw(BUFSIZ);
  363.         intmp = mallocw(BUFSIZ);
  364.         while(fgets(inbuf,BUFSIZ,fp) != NULLCHAR){
  365.             strcpy(intmp,inbuf);
  366.             if(Verbose){
  367.                 tprintf("%s",intmp);
  368.                 rflush();
  369.             }
  370.             if(cmdparse(Cmds,inbuf,NULL) != 0){
  371.                 tprintf("input line: %s",intmp);
  372.             }
  373.         }
  374.         fclose(fp);
  375.         free(inbuf);
  376.         free(intmp);
  377.     }
  378.  
  379.     Mprunning = 1;    /* we are on speed now */
  380.     Command->flowmode = 1;        /* set 'more' paging on command screen */
  381.  
  382.     /* Now loop forever, processing commands */
  383.     for(;;){
  384.         netPrompt ();
  385.         if(recv_mbuf(Command->input,&bp,0,NULLCHAR,0) != -1){
  386.             logcmd(bp->data);
  387.             (void)cmdparse(Cmds,bp->data,Lastcurr);
  388.             free_p(bp);
  389.         }
  390.     }
  391. }
  392.  
  393.  
  394. int
  395. chksession (sp)
  396. struct session *sp;
  397. {
  398.     return (((sp->type != COMMAND) && (sp != Trace) && (sp->type != FREE)) ? 1 : 0);
  399. }
  400.  
  401.  
  402. /* Keyboard input process */
  403. /* Modified to support F-key session switching,
  404.  * from the WNOS3 sources - WG7J
  405.  */
  406. void
  407. keyboard(i,v1,v2)
  408. int i;
  409. void *v1;
  410. void *v2;
  411. {
  412. int c;
  413. struct mbuf *bp;
  414. register int j,k;
  415. struct session *sp;
  416. int got = 0;
  417.  
  418.     /* Keyboard process loop */
  419.     for(;;){
  420.         c = kbread();
  421. #if    (!defined(MSDOS) || defined(ESCAPE))
  422.         if(c == Escape && Escape != 0)
  423.             c = -2;
  424. #endif
  425.         if(c == -2 && Current != Command){
  426.             /* Save current tty mode and set cooked */
  427. /*            swapscreen(Current,Command); */
  428.             Lastcurr = Current;
  429.             Current = Command;
  430.             swapscreen(Lastcurr,Current);
  431. /*            displayStatLine (0L); */
  432.             /* set 'more' paging on command screen */
  433.             Command->flowmode = 1;
  434.         }
  435.         if(c < -2) {             /* F1 to F9 (or INSERT) pressed */
  436.         switch (c)    { 
  437. #ifdef TRACE
  438.             case -11:    /* If F9 is pressed, -11 is returned and we swap to Trace - WG7J */
  439.                 if(Tracesession) {
  440.                     if(Current != Trace){
  441.                         /* Save current tty mode and set cooked */
  442. /*                        swapscreen(Current,Trace); */
  443.                         Lastcurr = Current;
  444.                         Current = Trace;
  445.                         swapscreen(Lastcurr,Current);
  446.                         /* turn off 'more' paging on trace screen */
  447.                         Trace->flowmode = 0;
  448.                     } else {
  449.                         /* Toggle back to previous session */
  450. /*                        swapscreen(Trace,Lastcurr); */
  451.                         Current = Lastcurr;
  452.                         Lastcurr = Trace;
  453.                         swapscreen(Lastcurr,Current);
  454.                     }
  455.                 }
  456.                 break;
  457. #endif
  458.             case -105:    /* INSERT pressed, statline toggle */
  459.                 statLineToggle ();
  460.                 break;
  461.             case -106:    /* DEL pressed, toggle flow control */
  462.                 Current->flowmode ^= 1;
  463.                 break;
  464.             case -107:    /* HOME pressed, kick current session */
  465.                 dokick (0, 0, Current);
  466.                 break;
  467.             case -108:    /* END pressed, end current session */
  468.                 doreset (0, 0, Current);
  469.                 break;
  470.             case -109:    /* PGUP pressed, goto previous session */
  471.                 j = (Current->index - 1) ? Current->index - 1 : Nsessions - 1;
  472.                 for(sp = &Sessions[j]; sp > Sessions; sp--)
  473.                     if ((got = chksession (sp)) != NULL)
  474.                         break;
  475.                 if (!got)
  476.                     for(sp = &Sessions[Nsessions - 1]; sp > Current; sp--)
  477.                         if ((got = chksession (sp)) != NULL)
  478.                             break;
  479.                 if (got)    {
  480. /*                    swapscreen(Current,sp); */
  481.                     Lastcurr = Current;
  482.                     Current = sp;
  483.                     swapscreen(Lastcurr,Current);
  484.                 }
  485.                 break;
  486.             case -110:    /* PGDN pressed, goto next session */
  487.                 for(sp = &Sessions[Current->index + 1]; sp < &Sessions[Nsessions]; sp++)
  488.                     if ((got = chksession (sp)) != NULL)
  489.                         break;
  490.                 if (!got)
  491.                     for(sp = Sessions; sp < Current; sp++)
  492.                         if ((got = chksession (sp)) != NULL)
  493.                             break;
  494.                 if (got)    {
  495. /*                    swapscreen(Current,sp); */
  496.                     Lastcurr = Current;
  497.                     Current = sp;
  498.                     swapscreen(Lastcurr,Current);
  499.                 }
  500.                 break;
  501.             default:
  502.                 k = (-1 * c) - 2;
  503.                 for(sp = Sessions, j = 0; sp < &Sessions[Nsessions]; sp++) {
  504.                     if(sp->type == COMMAND)
  505.                         continue;
  506.                     j++;
  507.                     if(sp->type != FREE && j == k) {
  508. /*                        swapscreen(Current,sp); */
  509.                         Lastcurr = Current;
  510.                         Current = sp;
  511.                         swapscreen(Lastcurr,Current);
  512.                         break;
  513.                     }
  514.                 }
  515.         }
  516.         }
  517.         
  518. /*        Current->row = MOREROWS; */
  519.         Current->row = SCREENlength - 1 - (Current->split * 2);
  520.         psignal(&Current->row,1);
  521.         if(c >= 0){
  522.             /* If the screen driver was in morewait state, this char
  523.              * has woken him up. Toss it so it doesn't also get taken
  524.              * as normal input. If the char was a command escape,
  525.              * however, it will be accepted; this gives the user
  526.              * a way out of lengthy output.
  527.              */            
  528.             if(!Current->morewait
  529.              && (bp = ttydriv(Current,c)) != NULLBUF){
  530.                 send_mbuf(Current->input,bp,0,NULLCHAR,0);
  531.             }
  532.         }
  533.     }
  534. }
  535.  
  536. extern int Kblocked;
  537. extern char *Kbpasswd;
  538. #ifdef LOCK
  539.  
  540. /*Lock the keyboard*/
  541. int
  542. dolock(argc,argv,p)
  543. int argc;
  544. char *argv[];
  545. void *p;
  546. {
  547.  
  548.     extern char Noperm[];
  549.  
  550.     /*allow only keyboard users to access the lock command*/
  551.     if(Curproc->input != Command->input) {
  552.         tputs(Noperm);
  553.         return 0;
  554.     }
  555.     if(argc == 1) {
  556.         if(Kbpasswd == NULLCHAR)
  557.             tputs("Set password first\n");
  558.         else {
  559.             Kblocked = 1;
  560.             tputs("Keyboard locked\n");
  561.             Command->ttystate.echo = 0; /* Turn input echoing off! */
  562.         }
  563.         return 0;
  564.     }
  565.     if(argc == 3) {
  566.         if(*argv[1] == 'p') {   /*set the password*/
  567.             if(Kbpasswd != NULLCHAR){
  568.                 free(Kbpasswd);
  569.                 Kbpasswd = NULLCHAR;        /* reset the pointer */
  570.             }
  571.         if(!strlen(argv[2]))
  572.             return 0;           /* clearing the buffer */
  573.         Kbpasswd = strdup(argv[2]);
  574.         return 0;
  575.         }
  576.     }
  577.  
  578.     tputs("Usage: lock password \"<unlock password>\"\nor    'lock' to lock the keyboard\n");
  579.  
  580.     return 0;
  581. }
  582.  
  583. #endif
  584.  
  585. /* Choose the prompt type */
  586. int
  587. doprompt(argc,argv,p)
  588. int argc;
  589. char *argv[];
  590. void *p;
  591. {
  592. char *str;
  593.  
  594.     if(argc == 1) {
  595.         switch (PromptType)    {
  596.             case 2:        str = "Dirname";
  597.                     break;
  598.             case 1:        str = "Hostname";
  599.                     break;
  600.             default:    str = "Normal";
  601.         }
  602.         tprintf ("Prompt: %s\n", str);
  603.             return 0;
  604.     }
  605.         if(*argv[1] == 'h')    /* use the hostname */
  606.             PromptType = 1;
  607.         else if (*argv[1] == 'd')    /* use the dirname */
  608.             PromptType = 2;
  609.         else if (*argv[1] == 'n')    /* use the normal prompt */
  610.             PromptType = 0;
  611.         else
  612.         tputs("Usage: prompt [hostname | dirname | normal]\n");
  613.     return 0;
  614. }
  615.  
  616. #ifdef ALLCMD
  617. /* Standard commands called from main */
  618. int
  619. dodelete(argc,argv,p)
  620. int argc;
  621. char *argv[];
  622. void *p;
  623. {
  624. int i;
  625. char filenm[13], *cp, fullname[128];
  626. unsigned attr;
  627. char fname[128];
  628.  
  629.     for(i=1;i < argc; i++)    {
  630.         strcpy(fname,make_fname(Command->curdirs->dir,argv[i]));
  631.         if (!_dos_getfileattr (fname, &attr) && (attr & FA_DIREC))    {
  632.             strcat (fname, "/*.*");
  633.             tputs ("All files in directory will be deleted!\nAre you sure (Y/N)? ");
  634.             usflush(Curproc->output);
  635.             recvline (Curproc->input, filenm, 13);
  636.             if (toupper (*filenm) != 'Y')
  637.                 continue;
  638.             cp = (char *) 1;
  639.         }
  640.         filedir(fname, 0, filenm);
  641.         if ((cp = strrchr (fname, '/')) != NULLCHAR)
  642.             *cp = 0;
  643.         for ( ; *filenm; filedir (fname, 1, filenm))  {
  644.             if (*filenm == '.' && (!filenm[1] || (filenm[1] == '.' && !filenm[2])))
  645.                 continue;
  646.             sprintf (fullname, "%s%s%s", (cp) ? fname : "", (cp) ? "/" : "", filenm);
  647.             if(unlink(fullname) == -1)
  648.                 tprintf("Can't delete %s: %s\n", fullname,sys_errlist[errno]);
  649.         }
  650.     }
  651.     return 0;
  652. }
  653.  
  654.  
  655. int
  656. dorename(argc,argv,p)
  657. int argc;
  658. char *argv[];
  659. void *p;
  660. {
  661. char fname1[128];
  662. char fname2[128];
  663.  
  664.     strcpy(fname1,make_fname(Command->curdirs->dir,argv[1]));
  665.     strcpy(fname2,make_fname(Command->curdirs->dir,argv[2]));
  666.     if(rename(fname1,fname2) == -1)
  667.         tprintf("Can't rename: %s\n",sys_errlist[errno]);
  668.     return 0;
  669. }
  670.  
  671.  
  672. int
  673. docopy(argc,argv,p)
  674. int argc;
  675. char *argv[];
  676. void *p;
  677. {
  678. register FILE *old, *new;
  679. register int ch;
  680. register unsigned char count;
  681. unsigned attr;
  682. char filenm[13], *dirnam = NULL, *cp, fullname[512];
  683. int usedir = 0;
  684. char fname[128], fname2[128];
  685.  
  686.     if (argc > 2)    {
  687.         strcpy(fname2,make_fname(Command->curdirs->dir,argv[2]));
  688.         _dos_getfileattr (fname2, &attr);
  689.         if(attr & FA_DIREC)    {
  690.             usedir = 1;
  691.             dirnam = fname2; 
  692.         }
  693.     } else
  694.         usedir = 1;
  695.     strcpy(fname,make_fname(Command->curdirs->dir,argv[1]));
  696.     if (!_dos_getfileattr (fname, &attr) && (attr & FA_DIREC))    {
  697.         strcat (fname, "/*.*");
  698.         cp = (char *) 1;
  699.     }
  700.     filedir (fname, 0, filenm);
  701.     if ((cp = strrchr (fname, '/')) != NULLCHAR)
  702.         *cp = 0;
  703.     for ( ; *filenm; filedir (fname, 1, filenm))    {
  704.         if (*filenm == '.' && (!filenm[1] || (filenm[1] == '.' && !filenm[2])))
  705.             continue;
  706.         sprintf (fullname, "%s%s%s", (cp) ? fname : "", (cp) ? "/" : "", filenm);
  707.         if((old = fopen(fullname,READ_BINARY)) == NULL) {
  708.             tprintf("Can't open %s: %s\n",fullname,sys_errlist[errno]);
  709.             continue;
  710.         }
  711.         sprintf (fullname, "%s%s%s", (dirnam) ? dirnam : "", (dirnam) ? "/" : "", (usedir) ? filenm : fname2);
  712.         if((new = fopen(fullname,WRITE_BINARY)) == NULL) {
  713.             tprintf("Can't open %s: %s\n",fullname,sys_errlist[errno]);
  714.             fclose (old);
  715.             continue;
  716.         }
  717.         strlwr (fullname);
  718.         tprintf ("Copying '%s'...\n", fullname);
  719.         /* Now go copy */
  720.         count = 0;
  721.         while((ch = fgetc(old)) != EOF) {
  722.             fputc(ch,new);
  723.             if(!(++count))      /* be polite to other users */
  724.                 pwait(NULL);
  725.         }
  726.         fclose(old);
  727.         fclose(new);
  728.         if (!usedir)
  729.             break;
  730.     }
  731.     return 0;
  732. }
  733. #endif /*ALLCMD*/
  734.  
  735. /*this is also called from the remote-server for the 'exit' command - WG7J*/
  736. void
  737. where_outta_here(resetme)
  738. int resetme;
  739. {
  740.     int i;
  741.     time_t StopTime;
  742.     FILE *fp;
  743.     char *inbuf,*intmp;
  744.  
  745.     if (NextCmd)
  746.         NextCmd = 1;
  747. /*    inbuf = NextCmdMsg;
  748.       NextCmdMsg = NULLCHAR;
  749.       free (inbuf);        */
  750.  
  751.     /* Execute sequence of commands taken from file "~/onexit.nos" */
  752.     /* From iw0cnb */
  753.     if((fp = fopen(Onexit,READ_TEXT)) != NULLFILE){
  754.         inbuf = mallocw(BUFSIZ);
  755.         intmp = mallocw(BUFSIZ);
  756.         while(fgets(inbuf,BUFSIZ,fp) != NULLCHAR){
  757.             strcpy(intmp,inbuf);
  758.             if(Verbose){
  759.                 tprintf("%s",intmp);
  760.                 rflush();
  761.             }
  762.             if(cmdparse(Cmds,inbuf,NULL) != 0){
  763.                 tprintf("input line: %s",intmp);
  764.             }
  765.         }
  766.         fclose(fp);
  767.         free(inbuf);
  768.         free(intmp);
  769.     }
  770.     StopTime = time(&StopTime);
  771.     main_exit = TRUE;    /* let everyone know we're out of here */
  772.     reset_all();
  773.     if(Dfile_updater != NULLPROC)
  774.         alert(Dfile_updater,0);    /* don't wait for timeout */
  775.     for(i=0;i<100;i++)
  776.         pwait(NULL);    /* Allow tasks to complete */
  777. #ifdef TRACE
  778.     shuttrace();
  779. #endif
  780. #if defined(TNOS) && !defined(TNOS_68K)
  781.     VMSterm ();
  782. #endif
  783.     log(-1,"TNOS was stopped");
  784.     if(Logfp){
  785.         fclose(Logfp);
  786.         Logfp = NULLFILE;
  787.     }
  788.     iostop();
  789.     if(resetme)
  790.         sysreset();
  791.     freehistory ();
  792.     free_dirs(Command->curdirs);         
  793. #ifdef TNOS_68K
  794.     alm_delete (TNOS_68KAlarm);
  795. #endif
  796.     exit(0);
  797. }
  798.  
  799. int
  800. doexit(argc,argv,p)
  801. int argc;
  802. char *argv[];
  803. void *p;
  804. {
  805. int c;
  806. struct mbuf *bp;
  807.  
  808.     if(Curproc->input != Command->input)
  809.         return -2;  /*probably mailbox-sysop */
  810.     tputs ("\007Exit TNOS: Are you sure? ");
  811.     tflush ();
  812.     recv_mbuf(Command->input,&bp,0,NULLCHAR,0);
  813.     c = bp->data[0];
  814.     if(c != 'y' && c != 'Y')
  815.         return 0;   /* signal delete of message */
  816.     where_outta_here(0); /*No reset!*/
  817.     return 0;   /* To satisfy lint */
  818. }
  819.  
  820. int
  821. dohostname(argc,argv,p)
  822. int argc;
  823. char *argv[];
  824. void *p;
  825. {
  826.     if(argc < 2)
  827.         tprintf("%s\n",Hostname);
  828.     else {
  829.         struct iface *ifp;
  830.         char *name;
  831.  
  832.                 if((ifp = if_lookup(argv[1])) != NULLIF){
  833.             if((name = resolve_a(ifp->addr, FALSE)) == NULLCHAR){
  834.                 tprintf("Interface address not resolved\n");
  835.                 return 1;
  836.             } else {
  837.                 if(Hostname != NULLCHAR)
  838.                     free(Hostname);
  839.                 Hostname = name;
  840.                 tprintf("Hostname set to %s\n", name );
  841.             }
  842.         } else {
  843.             if(Hostname != NULLCHAR)
  844.                 free(Hostname);
  845.             Hostname = strdup(argv[1]);
  846.             /* Remove trailing dot */
  847.             if(Hostname[strlen(Hostname)] == '.')
  848.                 Hostname[strlen(Hostname)] = '.';
  849.         }
  850.     }
  851.     return 0;
  852. }
  853.  
  854. int
  855. dolog(argc,argv,p)
  856. int argc;
  857. char *argv[];
  858. void *p;
  859. {
  860. static char *logname;
  861. char fname[128];
  862.  
  863.     if(argc < 2){
  864.         if(Logfp)
  865.             tprintf("Logging to %s\n",logname);
  866.         else
  867.             tprintf("Logging off\n");
  868.         return 0;
  869.     }
  870.     if(Logfp){
  871.         log(-1,"TNOS log closed");
  872.         fclose(Logfp);
  873.         Logfp = NULLFILE;
  874.         free(logname);
  875.         logname = NULLCHAR;
  876.     }
  877.     if(strcmp(argv[1],"stop") && strcmp(argv[1], "off")){
  878.         strcpy(fname,make_fname(Command->curdirs->dir,argv[1]));
  879.         logname = strdup(fname);
  880.         Logfp = fopen(logname,APPEND_TEXT);
  881.         log(-1,"TNOS v%s was started at %s", Version, ctime(&StartTime));
  882. #ifdef    MSDOS
  883.         log(-1,NosLoadInfo, _CS, _DS);
  884. #endif
  885.     }
  886.     return 0;
  887. }
  888.  
  889.  
  890. /* Attach an interface
  891.  * Syntax: attach <hw type> <I/O address> <vector> <mode> <label> <bufsize> [<speed>]
  892.  */
  893. int
  894. doattach(argc,argv,p)
  895. int argc;
  896. char *argv[];
  897. void *p;
  898. {
  899.     return subcmd(Attab,argc,argv,p);
  900. }
  901. /* Manipulate I/O device parameters */
  902. int
  903. doparam(argc,argv,p)
  904. int argc;
  905. char *argv[];
  906. void *p;
  907. {
  908.     int param,set;
  909.     int32 val;
  910.     register struct iface *ifp;
  911.  
  912.     if((ifp = if_lookup(argv[1])) == NULLIF){
  913.         tprintf(Badinterface,argv[1]);
  914.         return 1;
  915.     }
  916.     if(ifp->ioctl == NULL){
  917.         tprintf("Not supported\n");
  918.         return 1;
  919.     }
  920.     if(argc < 3){
  921.         for(param=1;param<=16;param++){
  922.             val = (*ifp->ioctl)(ifp,param,FALSE,0L);
  923.             if(val != -1)
  924.                 tprintf("%s: %ld\n",parmname(param),val);
  925.         }
  926.         return 0;
  927.     }
  928.     param = devparam(argv[2]);
  929.     if(param == -1){
  930.         tprintf("Unknown parameter %s\n",argv[2]);
  931.         return 1;
  932.     }
  933.     if(argc < 4){
  934.         set = FALSE;
  935.         val = 0L;
  936.     } else {
  937.         set = TRUE;
  938.         val = atol(argv[3]);
  939.     }
  940.     val = (*ifp->ioctl)(ifp,param,set,val);
  941.     if(val == -1)
  942.         tprintf("Parameter %s not supported\n",argv[2]);
  943.     else
  944.         tprintf("%s: %ld\n",parmname(param),val);
  945.     return 0;    
  946. }
  947.  
  948. /* Display or set IP interface control flags */
  949. int
  950. domode(argc,argv,p)
  951. int argc;
  952. char *argv[];
  953. void *p;
  954. {
  955.     register struct iface *ifp;
  956.  
  957.     if((ifp = if_lookup(argv[1])) == NULLIF){
  958.         tprintf(Badinterface,argv[1]);
  959.         return 1;
  960.     }
  961.     if(argc < 3){
  962.         tprintf("%s: %s\n",ifp->name,
  963.          (ifp->flags & CONNECT_MODE) ? "VC mode" : "Datagram mode");
  964.         return 0;
  965.     }
  966.     switch(argv[2][0]){
  967.     case 'v':
  968.     case 'c':
  969.     case 'V':
  970.     case 'C':
  971.         ifp->flags |= CONNECT_MODE;
  972.         break;
  973.     case 'd':
  974.     case 'D':
  975.         ifp->flags &= ~CONNECT_MODE;
  976.         break;
  977.     default:
  978.         tprintf("Usage: %s [vc | datagram]\n",argv[0]);
  979.         return 1;
  980.     }
  981.     return 0;
  982. }
  983.  
  984. #if    (!defined(MSDOS) || defined(ESCAPE))
  985. int
  986. doescape(argc,argv,p)
  987. int argc;
  988. char *argv[];
  989. void *p;
  990. {
  991.     if(argc < 2)
  992.         tprintf("0x%x\n",Escape);
  993.     else 
  994.         Escape = *argv[1];
  995.     return 0;
  996. }
  997. #endif    MSDOS
  998. /* Generate system command packet. Synopsis:
  999.  * remote [-p port#] [-k key] [-a hostname] <hostname> reset|exit|kickme
  1000.  */
  1001. int
  1002. doremote(argc,argv,p)
  1003. int argc;
  1004. char *argv[];
  1005. void *p;
  1006. {
  1007.     struct sockaddr_in fsock;
  1008.     int s,c;
  1009.     char *data,x;
  1010.     int16 port,len;
  1011.     char *key = NULLCHAR;
  1012.     int klen;
  1013.     int32 addr = 0;
  1014.     char *cmd,*host;
  1015.  
  1016.     port = IPPORT_REMOTE;    /* Set default */
  1017.     optind = 1;        /* reinit getopt() */
  1018.     while((c = getopt(argc,argv,"a:p:k:s:")) != EOF){
  1019.         switch(c){
  1020.         case 'a':
  1021.             if((addr = resolve(optarg)) == 0){
  1022.                 tprintf("Host %s unknown\n",optarg);
  1023.                 return -1;
  1024.             }
  1025.             break;
  1026.         case 'p':
  1027.             port = atoi(optarg);
  1028.             break;
  1029.         case 'k':
  1030.             key = optarg;
  1031.             klen = strlen(key);
  1032.             break;
  1033.         case 's':
  1034.             Rempass = strdup(optarg);
  1035.             return 0;    /* Only set local password */
  1036.         }
  1037.     }
  1038.     if(optind > argc - 2){
  1039.         tprintf("Insufficient args\n");
  1040.         return -1;
  1041.     }
  1042.     host = argv[optind];
  1043.     cmd = argv[optind + 1];
  1044.     if((s = socket(AF_INET,SOCK_DGRAM,0)) == -1){
  1045.         tprintf("socket failed\n");
  1046.         return 1;
  1047.     }
  1048.     len = 1;
  1049.     /* Did the user include a password or kickme target? */
  1050.     if(addr != 0 && cmd[0] == 'k')
  1051.         len += sizeof(int32);
  1052.  
  1053.     if(key != NULLCHAR && (cmd[0] == 'r' || cmd[0] == 'e')) 
  1054.         len += klen;
  1055.  
  1056.     if(len == 1)
  1057.         data = &x;
  1058.     else
  1059.         data = mallocw(len);
  1060.  
  1061.     fsock.sin_family = AF_INET;
  1062.     if((fsock.sin_addr.s_addr = resolve(host)) == 0){
  1063.         tprintf("Host %s unknown\n",host);
  1064.         goto cleanup;
  1065.     }
  1066.     fsock.sin_port = port;
  1067.  
  1068.     switch(cmd[0]){
  1069.     case 'r':
  1070.         data[0] = SYS_RESET;
  1071.         if(key != NULLCHAR)
  1072.             strncpy(&data[1],key,klen);
  1073.         break;
  1074.     case 'e':
  1075.         data[0] = SYS_EXIT;
  1076.         if(key != NULLCHAR)
  1077.             strncpy(&data[1],key,klen);
  1078.         break;
  1079.     case 'k':
  1080.         data[0] = KICK_ME;
  1081.         if(addr != 0)
  1082.             put32(&data[1],addr);
  1083.         break;
  1084.     default:
  1085.         tprintf("Unknown command %s\n",cmd);
  1086.         goto cleanup;
  1087.     }
  1088.     /* Form the command packet and send it */
  1089.     if(sendto(s,data,len,0,(char *)&fsock,sizeof(fsock)) == -1){
  1090.         tprintf("sendto failed: %s\n",sys_errlist[errno]);
  1091.         goto cleanup;
  1092.     }
  1093. cleanup:
  1094.     if(data != &x)
  1095.         free(data);
  1096.     close_s(s);
  1097.     return 0;
  1098. }
  1099.  
  1100. #if (defined(ALLCMD) || defined(ALLSESSIONS))
  1101. int
  1102. morecmd(argc,argv,p)
  1103. int argc;
  1104. char *argv[];
  1105. void *p;
  1106. {
  1107.     struct session *sp;
  1108.     FILE *fp;
  1109.     char buf[81];
  1110.     char fname[256];
  1111.     int row;
  1112.  
  1113.     int usesession = 0;
  1114.  
  1115.     /* Use a session if this comes from console - WG7J*/
  1116.     if(Curproc->input == Command->input) {
  1117.         usesession = 1;
  1118.         if((sp = newsession(argv[1],MORE,0)) == NULLSESSION){
  1119.             return 1;
  1120.         }
  1121.         /* Put tty into raw mode so single-char responses will work */
  1122.         sp->ttystate.echo = sp->ttystate.edit = 0;
  1123.         row = SCREENlength;
  1124.     }
  1125.  
  1126.     strcpy(fname,make_fname(Command->curdirs->dir,argv[1]));
  1127.     if((fp = fopen(fname,READ_TEXT)) == NULLFILE){
  1128.         tprintf(NoRead,fname,sys_errlist[errno]);
  1129.         if(usesession) {
  1130.             keywait(NULLCHAR,1);
  1131.             freesession(sp);
  1132.         }
  1133.         return 1;
  1134.     }
  1135.     while(fgets(buf,sizeof(buf),fp),!feof(fp)){
  1136.         if((argc < 3) || (strstr(buf,argv[2])!=NULLCHAR)) {
  1137.             tprintf("%s",buf);
  1138.             if(usesession) {
  1139.                 if(--row == 0){
  1140.                     row = keywait("--More--",0);
  1141.                     switch(row){
  1142.                     case -1:
  1143.                     case 'q':
  1144.                     case 'Q':
  1145.                     case 'n':
  1146.                     case 'N':
  1147.                         goto done;
  1148. #ifndef TNOS_68K
  1149.                     case '\n':
  1150. #else
  1151.             case '\l':
  1152. #endif
  1153.                     case '\r':
  1154.                         row = 1;
  1155.                         break;
  1156.                     case ' ':
  1157.                     default:
  1158. /*                        row = Numrows - 1;    */
  1159.             row = SCREENlength;
  1160.                     }
  1161.                 }
  1162.             }
  1163.         }
  1164.     }
  1165. done:    fclose(fp);
  1166.     if(usesession) {
  1167.         keywait(NULLCHAR,1);
  1168.         freesession(sp);
  1169.     }
  1170.     return 0;
  1171. }
  1172.  
  1173. int
  1174. domore(argc,argv,p)
  1175. int argc;
  1176. char *argv[];
  1177. void *p;
  1178. {
  1179.     char **pargv;
  1180.     int i;
  1181.  
  1182.     if(Curproc->input == Command->input) {
  1183.         /* Make private copy of argv and args,
  1184.          * spawn off subprocess and return.
  1185.          */
  1186.         pargv = (char **)callocw(argc + 1,sizeof(char *));
  1187.         for(i=0;i<argc;i++)
  1188.             pargv[i] = strdup(argv[i]);
  1189.         pargv[i] = NULL;
  1190.         newproc("more",512,(void (*)())morecmd,argc,(void *)pargv,p,1);
  1191.     } else
  1192.         morecmd(argc,argv,p);
  1193.     return 0;
  1194. }
  1195.  
  1196.  
  1197.  
  1198. int
  1199. dotail(argc,argv,p)
  1200. int argc;
  1201. char *argv[];
  1202. void *p;
  1203. {
  1204.     register int handle, i;
  1205.     register unsigned line = 0, rdsize = 2000;
  1206.     long length;
  1207.     char *buffer, fname[128];
  1208.     register int numlines = 18;
  1209.  
  1210.     if (argc == 3)    {
  1211.         numlines = atoi (argv[2]);
  1212.         if (!numlines)
  1213.             numlines = 18;
  1214.         else
  1215.             rdsize = numlines * 100;
  1216.     }
  1217.     buffer = callocw(rdsize, sizeof (char));
  1218.  
  1219.     strcpy(fname,make_fname(Command->curdirs->dir,argv[1]));
  1220.     if ((handle = open (fname, O_BINARY | O_RDONLY)) == -1) {
  1221.         tprintf(NoRead,fname,sys_errlist[errno]);
  1222.         free(buffer);
  1223.         return -1;
  1224.     }
  1225.     length = filelength (handle);
  1226.  
  1227.     if (length > rdsize) {
  1228.         length -= rdsize;
  1229.     } else {
  1230.         rdsize = (int) length;
  1231.         length = 0;
  1232.     }
  1233.  
  1234.     lseek (handle, length, SEEK_SET);
  1235.     if (read (handle, buffer, rdsize) == -1) {
  1236.         tprintf(NoRead,fname,sys_errlist[errno]);
  1237.         close(handle);
  1238.         free(buffer);
  1239.         return -1;
  1240.     }
  1241.  
  1242.     for (i = rdsize - 1; i > 0; i--) {
  1243.         if (buffer[i] == '\n')
  1244.             line++;
  1245.         if (line == numlines)
  1246.             break;
  1247.     }
  1248.     for (; i < rdsize; i++)
  1249.         tputc(buffer[i]);
  1250.  
  1251.     tprintf("\n");
  1252.     close(handle);
  1253.     free(buffer);
  1254.     return 0;
  1255. }
  1256. #endif /*ALLCMD*/
  1257.  
  1258. /* No-op command */
  1259. int
  1260. donothing(argc,argv,p)
  1261. int argc;
  1262. char *argv[];
  1263. void *p;
  1264. {
  1265.     return 0;
  1266. }
  1267.  
  1268. int dosystime(argc,argv,p)
  1269. int argc;
  1270. char *argv[];
  1271. void *p;
  1272. {
  1273. long t;
  1274.  
  1275.     /* Get current time */
  1276.     time(&t);
  1277.  
  1278.     /* Print it */
  1279.     tprintf("System time at %s: %s",Hostname, ctime(&t));
  1280.     return 0;
  1281. }
  1282.  
  1283.  
  1284. static int SendError = 1;
  1285.  
  1286. int doerror(argc,argv,p)
  1287. int argc;
  1288. char *argv[];
  1289. void *p;
  1290. {
  1291.     return setbool(&SendError,"Mail errors",argc,argv);
  1292. }
  1293.  
  1294. /* Mail a system message to the sysop - WG7J */
  1295. void
  1296. mail_error(char *fmt, ...)
  1297. {
  1298.     FILE *txt;
  1299.     va_list ap;
  1300.     char *cp;
  1301.     long t;
  1302.     char fn[128];
  1303.  
  1304.     if(!SendError)
  1305.     return;
  1306.  
  1307.      /* Create the data file */
  1308.     if((txt = tmpfile()) == NULL)
  1309.     return;
  1310.  
  1311.     /* Get current time */
  1312.     time(&t);
  1313.  
  1314.     /* Print the text body */
  1315.     cp = ctime(&t);
  1316.     fprintf(txt,"On %s",cp);
  1317.     va_start(ap,fmt);
  1318.     vfprintf(txt,fmt,ap);
  1319.     va_end(ap);
  1320.     fputc('\n',txt);
  1321.     rewind (txt);
  1322.     rdaemon (txt, NULLCHAR, NULLCHAR, SysMessage, 'P', 0);
  1323.  
  1324.     fclose(txt);
  1325.  
  1326.     /* Now kick the smtp server */
  1327.     smtptick(NULL);
  1328. }
  1329.  
  1330. /* Log messages of the form
  1331.  * Tue Jan 31 00:00:00 1987 44.64.0.7:1003 open FTP
  1332.  */
  1333. #if    defined(ANSIPROTO)
  1334. void
  1335. log(int s,char *fmt, ...)
  1336. {
  1337. va_list ap;
  1338. char *cp;
  1339. long t;
  1340. int i;
  1341. struct sockaddr fsocket;
  1342. #ifdef    MSDOS
  1343. int fd;
  1344. #endif
  1345. char buf[80];
  1346.  
  1347.     va_start(ap,fmt);
  1348.     vsprintf(buf,fmt,ap);
  1349.     va_end(ap);
  1350.     statlog (buf);
  1351.  
  1352.     if(Logfp == NULLFILE)
  1353.         return;
  1354.  
  1355.     time(&t);
  1356.     cp = ctime(&t);
  1357.     rip(cp);
  1358.     i = SOCKSIZE;
  1359.     fprintf(Logfp,"%s",cp);
  1360.     if(getpeername(s,(char *)&fsocket,&i) != -1)
  1361.         fprintf(Logfp," %s",psocket(&fsocket));
  1362.  
  1363.     fprintf(Logfp," - %s\n", buf);
  1364.     fflush(Logfp);
  1365. #ifdef    MSDOS
  1366.     /* MS-DOS doesn't really flush files until they're closed */
  1367.     fd = fileno(Logfp);
  1368.     if((fd = dup(fd)) != -1)
  1369.         close(fd);
  1370. #endif
  1371.  
  1372. }
  1373. #else
  1374. /*VARARGS2*/
  1375. void
  1376. log(s,fmt,arg1,arg2,arg3,arg4,arg5)
  1377. int s;
  1378. char *fmt;
  1379. int arg1,arg2,arg3,arg4,arg5;
  1380. {
  1381. char *cp;
  1382. long t;
  1383. int fd,i;
  1384. struct sockaddr fsocket;
  1385. char buf[80];
  1386.  
  1387.     sprintf(buf,fmt,arg1,arg2,arg3,arg4,arg5);
  1388.     statlog (buf);
  1389.  
  1390.     if(Logfp == NULLFILE)
  1391.         return;
  1392.     time(&t);
  1393.     cp = ctime(&t);
  1394.     rip(cp);
  1395.     i = SOCKSIZE;
  1396.     fprintf(Logfp,"%s",cp);
  1397.     if(getpeername(s,(char *)&fsocket,&i) != -1)
  1398.         fprintf(Logfp," %s",psocket(&fsocket));
  1399.  
  1400.     fprintf(Logfp," - %s\n", buf);
  1401.     fflush(Logfp);
  1402. #ifdef    MSDOS
  1403.     /* MS-DOS doesn't really flush files until they're closed */
  1404.     fd = fileno(Logfp);
  1405.     if((fd = dup(fd)) != -1)
  1406.         close(fd);
  1407. #endif
  1408. }
  1409. #endif
  1410.  
  1411. int
  1412. dosource(argc,argv,p)
  1413. int argc;
  1414. char *argv[];
  1415. void *p;
  1416. {
  1417. int linenum = 0;
  1418. char *inbuf,*intmp;
  1419. FILE *fp;
  1420. char fname[128];
  1421.  
  1422.     /* Read command source file */
  1423.     strcpy(fname,make_fname(Command->curdirs->dir,argv[1]));
  1424.     if((fp = fopen(fname,READ_TEXT)) == NULLFILE){
  1425.         tprintf(NoRead,fname,sys_errlist[errno]);
  1426.         return 1;
  1427.     }
  1428.  
  1429.     inbuf = malloc(BUFSIZ);
  1430.     intmp = malloc(BUFSIZ);
  1431.     while(fgets(inbuf,BUFSIZ,fp) != NULLCHAR){
  1432.         strcpy(intmp,inbuf);
  1433.         linenum++;
  1434.         if(Verbose)
  1435.             tprintf("%s",intmp);
  1436.         if(cmdparse(Cmds,inbuf,NULL) != 0){
  1437.             tprintf("*** file \"%s\", line %d: %s\n",
  1438.                 argv[1],linenum,intmp);
  1439.         }
  1440.     }
  1441.     fclose(fp);
  1442.     free(inbuf);
  1443.     free(intmp);
  1444.     return 0;
  1445. }
  1446.  
  1447. /* if unattended mode is set - restrict ax25, telnet and maybe other sessions */
  1448. doattended(argc,argv,p)
  1449. int argc;
  1450. char *argv[];
  1451. void *p;
  1452. {
  1453.     return setbool(&Attended,"Attended flag",argc,argv);
  1454. }
  1455.  
  1456. /* if ThirdParty is not set - restrict the mailbox (S)end command to local only */
  1457. dothirdparty(argc,argv,p)
  1458. int argc;
  1459. char *argv[];
  1460. void *p;
  1461. {
  1462.     return setbool(&ThirdParty,"Third-Party mail flag",argc,argv);
  1463. }
  1464.  
  1465. #ifdef ALLCMD
  1466. int
  1467. domdump(argc,argv,p)
  1468. int argc;
  1469. char *argv[];
  1470. void *p;
  1471. {
  1472.     unsigned int i;
  1473.     char * addr;
  1474.     unsigned int len = 8 * 16;    /* default is 8 lines of hex dump */
  1475.  
  1476.     if(argc < 2 || argc > 3) {
  1477.         tprintf("Usage:- dump <hex-address | .> [decimal-range] \n");
  1478.         return 0;
  1479.     }
  1480.     if(argv[1][0] == '.')
  1481.         addr = DumpAddr;        /* Use last end address */
  1482.     else
  1483.         addr = ltop(htol(argv[1]));    /* get address of item being dumped */
  1484.  
  1485.     if(argc == 3) {
  1486.         len = atoi(argv[2]);
  1487.         len = ((len + 15) >> 4) << 4;    /* round up to modulo 16 */
  1488.     }
  1489.  
  1490.     if(len < 1 || len > 256) {
  1491.         tprintf("Invalid dump range. Valid is 1 to 256\n");
  1492.         return 0;
  1493.     }
  1494. #ifndef TNOS_68K
  1495.     tprintf("            Main Memory Dump Of Location %Fp\n", addr);
  1496. #else
  1497.     tprintf("            Main Memory Dump Of Location %08x\n", addr);
  1498. #endif
  1499.     tprintf("Addr (offset)           Hexadecimal                         Ascii\n");
  1500.     tprintf("----                    -----------                         -----\n");
  1501.  
  1502.     for(i = 0; i < len; i += 16)
  1503.         fmtline(i, (char *)(addr + i), 16);
  1504.     DumpAddr = (char *)(addr + i);        /* update address */
  1505.     return 0;
  1506. }
  1507.  
  1508. /* Print a buffer up to 16 bytes long in formatted hex with ascii
  1509.  * translation, e.g.,
  1510.  * 0000: 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f  0123456789:;<=>?
  1511.  */
  1512. static void
  1513. fmtline(addr,buf,len)
  1514. int16 addr;
  1515. char *buf;
  1516. int16 len;
  1517. {
  1518.     char line[81];
  1519.     register char *aptr,*cptr;
  1520.     register char c;
  1521.  
  1522.     memset(line,' ',sizeof(line));
  1523.     ctohex(line,(int16)hibyte(addr));
  1524.     ctohex(line+2,(int16)lobyte(addr));
  1525.     aptr = &line[6];
  1526.     cptr = &line[55];
  1527.     while(len-- != 0){
  1528.         c = *buf++;
  1529.         ctohex(aptr,(int16)uchar(c));
  1530.         aptr += 3;
  1531.         c &= 0x7f;
  1532.         if((c > 0x1f) && (c < 0x7f))
  1533.             *cptr++ = c;
  1534.         else
  1535.             *cptr++ = '.';
  1536.     }
  1537.     *cptr++ = '\0';
  1538.     tprintf("%s\n",line);
  1539. }
  1540. /* Convert byte to two ascii-hex characters */
  1541. static void
  1542. ctohex(buf,c)
  1543. register char *buf;
  1544. register int16 c;
  1545. {
  1546.     static char hex[] = "0123456789abcdef";
  1547.  
  1548.     *buf++ = hex[hinibble(c)];
  1549.     *buf = hex[lonibble(c)];
  1550. }
  1551. #endif
  1552.  
  1553. int
  1554. dowrite(argc,argv,p)
  1555. int argc;
  1556. char *argv[];
  1557. void *p;
  1558. {
  1559.     int i,s;
  1560.     struct mbx *m;
  1561.  
  1562.     if((s = atoi(argv[1])) == 0) { /* must be a name */
  1563.         /* check the mailbox users */
  1564.         for(i = 0; i < NUMMBX; i++){
  1565.             if((m = Mbox[i]) != NULLMBX){
  1566.                 if(!strcmp(m->name,argv[1]))
  1567.                     break;
  1568.             }
  1569.         }
  1570.         if(i == NUMMBX)
  1571.             return 0;
  1572.         s = m->user;
  1573.     }
  1574.     usprintf(s,FromSysop,argv[2]);
  1575.     usflush(s);
  1576.  
  1577.     return 0;
  1578. }
  1579.  
  1580. extern void conversWriteall __ARGS((char *str));
  1581.  
  1582. /* write a message to all nodeshell users
  1583.  * argv[1] is the message.
  1584.  */
  1585. int
  1586. dowriteall(argc,argv,p)
  1587. int argc;
  1588. char *argv[];
  1589. void *p;
  1590. {
  1591. register struct mbx *m;
  1592. int i;
  1593.  
  1594.     for(i = 0; i < NUMMBX; i++)
  1595.         if((m = Mbox[i]) != NULLMBX){
  1596.             usprintf(m->user,FromSysop,argv[1]);
  1597.             usflush(m->user);
  1598.         }
  1599. #ifdef CONVERS
  1600.    conversWriteall (argv[1]);
  1601. #endif
  1602.    return 0;
  1603. }
  1604.  
  1605.  
  1606. int
  1607. dostatus(argc,argv,p)
  1608. int argc;
  1609. char *argv[];
  1610. void *p;
  1611. {
  1612.     time_t nowtime, elapsedtime;
  1613.     unsigned int days,hrs,mins,secs;
  1614.  
  1615.     nowtime = time(&nowtime);            /* current time */
  1616.     elapsedtime = nowtime - StartTime;        /* nos elapsed time */
  1617.  
  1618.     tprintf(Nosversion,Version);
  1619.     tputs(Version2);
  1620.  
  1621. #ifdef    MSDOS
  1622.     tprintf(NosLoadInfo, _CS, _DS);
  1623. #endif
  1624.     tprintf("\nThe system time is %s", ctime(&nowtime));
  1625.     tprintf("TNOS was started on %s\n", ctime(&StartTime));
  1626.     secs = elapsedtime % 60;
  1627.     elapsedtime = elapsedtime / 60;
  1628.     mins = elapsedtime % 60;
  1629.     elapsedtime = elapsedtime / 60;
  1630.     hrs = elapsedtime % 24;
  1631.     elapsedtime = elapsedtime / 24;
  1632.     days = elapsedtime;
  1633.     tprintf("Elapsed time => %u days:%02u hours:%02u minutes:%02u seconds.\n\n",days,hrs,mins,secs);
  1634.     tprintf("Sessions = %-d, Sockets = %-d\n\n", Nsessions, Nusock);
  1635. #ifdef ALLCMD
  1636.     tprintf("The station is currently %sttended.\n", Attended ? "A" : "Una");
  1637.     tprintf("The 'Message Of The Day' is ");
  1638.     if(Motd != NULLCHAR)
  1639.         tprintf("\n%s",Motd);
  1640.     else
  1641.         tprintf("not set!\n");
  1642. #endif
  1643. #ifdef  __TURBOC__
  1644.     dofstat();        /* print status of open files */
  1645. #endif
  1646.     return 0;
  1647. }
  1648.  
  1649. #ifdef ALLCMD
  1650. int
  1651. domotd(argc,argv,p)
  1652. int argc;
  1653. char *argv[];
  1654. void *p;
  1655. {
  1656.     if(argc > 2) {
  1657.         tprintf("Usage: motd \"<your message>\"\n");
  1658.         return 1;
  1659.     }
  1660.  
  1661.     if(argc < 2) {
  1662.         if(Motd != NULLCHAR) 
  1663.             tprintf("%s",Motd);
  1664.     } else {
  1665.         if(Motd != NULLCHAR){
  1666.             free(Motd);
  1667.             Motd = NULLCHAR;        /* reset the pointer */
  1668.         }
  1669.  
  1670.         if(!strlen(argv[1]))
  1671.             return 0;            /* clearing the buffer */
  1672.  
  1673.         Motd = mallocw(strlen(argv[1])+5);    /* allow for the EOL char etc */
  1674.         strcpy(Motd, argv[1]);
  1675.         strcat(Motd, "\n");            /* add the EOL char */
  1676.     }
  1677.     return 0;
  1678. }
  1679. #endif /*ALLCMD*/
  1680.  
  1681. #ifdef nope
  1682. /* test the stktrace utility */
  1683. int dotest(int argc, char *argv[], void *p) {
  1684.  
  1685.     void *ptr = (void *) 0x12345678;
  1686.     free(ptr);
  1687.     return 0;
  1688. }
  1689. #endif
  1690.  
  1691. #ifdef    __TURBOC__
  1692. /*
  1693.  * Fstat utility code.
  1694.  * Converted to go into NOS by Kelvin Hill - G1EMM  April 9, 1990
  1695.  */
  1696.  
  1697. extern unsigned char _osmajor;
  1698.  
  1699. static char    *localcopy __ARGS((char DFAR *));
  1700. static char    *progname __ARGS((unsigned int));
  1701.  
  1702. int
  1703. dofstat()
  1704. {
  1705.     union REGS regs;
  1706.     struct SREGS segregs;
  1707.     char DFAR *pfiletab, DFAR * pnext, DFAR * fp;
  1708.     char DFAR *name, file[13], DFAR * plist, DFAR * entry;
  1709.     char ownername[9], ownerext[5];
  1710.     int nfiles, i, j, numhandles, entrylen;
  1711.     unsigned int access, devinfo, progpsp;
  1712.     long length, offset;
  1713.     int heading = 0;
  1714.  
  1715.     regs.h.ah = 0x52;    /* DOS list of lists */
  1716.     intdosx(®s, ®s, &segregs);
  1717.  
  1718.     /* make a pointer to start of master list */
  1719.     plist = (char DFAR *) MK_FP(segregs.es, regs.x.bx);
  1720.  
  1721.     /* pointer to start of file table */
  1722.     pfiletab = (char DFAR *) MK_FP(*(int DFAR *) (plist + 6), *(int DFAR *) (plist + 4));
  1723.  
  1724.     switch (_osmajor) {
  1725.     case 2:
  1726.         entrylen = 40;    /* DOS 2.x */
  1727.         break;
  1728.     case 3:
  1729.         entrylen = 53;    /* DOS 3.x */
  1730.         break;
  1731.     case 4:
  1732.     case 5:            /* DOS 5.x - like dos 4.x */
  1733.     case 6:            /* DOS 6.x - like dos 4.x */
  1734.         entrylen = 59;    /* DOS 4.x - I do not know what is in the
  1735.                  * extra 6 bytes */
  1736.         break;
  1737.     default:
  1738. /*
  1739.         tprintf("Sorry, cannot handle this version of MS-DOS");
  1740. */
  1741.         return 1;
  1742.     }
  1743.  
  1744.     for (;;) {
  1745.         /* pointer to next file table */
  1746.         pnext = (char DFAR *) MK_FP(*(int DFAR *) (pfiletab + 2), *(int DFAR *) (pfiletab + 0));
  1747.         nfiles = *(int DFAR *) (pfiletab + 4);
  1748. #ifdef DEBUG
  1749.         tprintf("\nFile table at %Fp entries for %d files\n", pfiletab, nfiles);
  1750. #endif
  1751.         for (i = 0; i < nfiles; i++) {
  1752.  
  1753.             /*
  1754.              * cycle through all files, quit when we reach an
  1755.              * unused entry
  1756.              */
  1757.             entry = pfiletab + 6 + (i * entrylen);
  1758.             if (_osmajor >= 3) {
  1759.                 name = entry + 32;
  1760.                 strncpy(file, localcopy(name), 11);
  1761.                 file[11] = '\0';
  1762.                 numhandles = *(int DFAR *) (entry + 0);
  1763.                 access = (int) *(char DFAR *) (entry + 2);
  1764.                 length = *(long DFAR *) (entry + 17);
  1765.                 offset = *(long DFAR *) (entry + 21);
  1766.                 devinfo = *(int DFAR *) (entry + 5);
  1767.                 progpsp = *(int DFAR *) (entry + 49);
  1768.             } else {
  1769.                 name = entry + 4;
  1770.                 strncpy(file, localcopy(name), 11);
  1771.                 file[11] = '\0';
  1772.                 numhandles = (int) *(char DFAR *) (entry + 0);
  1773.                 access = (int) *(char DFAR *) (entry + 1);
  1774.                 length = *(long DFAR *) (entry + 19);
  1775.                 offset = *(long DFAR *) (entry + 36);
  1776.                 devinfo = (int) *(char DFAR *) (entry + 27);
  1777.             }
  1778.             if ((strlen(file) > 0) && (numhandles > 0) && !(devinfo & 0x80)) {
  1779.                 if(!heading) {
  1780.                     tprintf("\n");
  1781.                     tprintf("                 Table of Open Files.\n");
  1782.                     tprintf("                 --------------------\n");
  1783.                     tprintf("Name           length   offset hnd acc PSP device type/owner\n");
  1784.                     tprintf("----           ------   ------ --- --- --- -----------------\n");
  1785.                     heading++;        /* header now printed */
  1786.                 }
  1787.                 tprintf("%8.8s.%3.3s %8ld %8ld  %2d ",
  1788.                        file, &file[8], length, offset, numhandles);
  1789.                 switch (access) {
  1790.                 case 0:
  1791.                     tprintf("r  ");
  1792.                     break;
  1793.                 case 1:
  1794.                     tprintf("w  ");
  1795.                     break;
  1796.                 case 2:
  1797.                     tprintf("rw ");
  1798.                     break;
  1799.                 default:
  1800.                     tprintf("   ");
  1801.                 }
  1802.                 if (_osmajor >= 3)
  1803.                     tprintf("%04X ", progpsp);
  1804.                 else
  1805.                     tprintf("---- ");
  1806.                 tprintf("drive %c: ", 'A' + (devinfo & 0x1F));
  1807.                 if (devinfo & 0x8000)
  1808.                     tprintf("(network) ");
  1809.                 if (_osmajor >= 3) {
  1810.                     /*
  1811.                      * only DOS 3+ can find out
  1812.                      * the name of the program
  1813.                      */
  1814.                     fnsplit(progname(progpsp), NULL, NULL, ownername, ownerext);
  1815.                     tprintf("   [%s%s]\n", strlwr(ownername), strlwr(ownerext));
  1816.                 } else {
  1817.                     tprintf("\n");
  1818.                 }
  1819.             }
  1820.             if (strlen(file) == 0)
  1821.                 return 0;
  1822.         }
  1823.         pfiletab = pnext;
  1824.     }
  1825. }
  1826.  
  1827. /* Make a copy of a string pointed to by a far pointer */
  1828. static char *
  1829. localcopy(s)
  1830. char DFAR *s;
  1831. {
  1832.     static char localstring[256];
  1833.     char DFAR *p = s;
  1834.     char *l = localstring;
  1835.     int i = 0;
  1836.  
  1837.     while (*p != NULL && i++ < 255) {
  1838.         *l++ = *p++;
  1839.     }
  1840.  
  1841.     *l = '\0';
  1842.  
  1843.     return (localstring);
  1844. }
  1845.  
  1846. /*
  1847.  * Return a near pointer to a character string with the full path name of the
  1848.  * program whose PSP is given in the argument.  If the argument is invalid,
  1849.  * this may return gibberish but I don't know how to tell Offset 0x2C in the
  1850.  * PSP in the segment address of the environment of a program.  Beyond the
  1851.  * last environment string is a null marker, a word count (usually 1), then
  1852.  * the full pathname of the owner of the environment This only works for DOS
  1853.  * 3+
  1854.  */
  1855. static char *
  1856. progname(pid)
  1857. unsigned int pid;
  1858. {
  1859.     unsigned DFAR   *envsegptr;    /* Pointer to seg address of
  1860.                      * environment */
  1861.     char DFAR       *envptr;    /* Pointer to pid's environment     */
  1862.     unsigned DFAR   *envsizeptr;    /* Pointer to environment size */
  1863.     unsigned        envsize;/* Size of pid's environment */
  1864.     unsigned        ppid;    /* Parent psp address */
  1865.  
  1866.     /* find the parent process psp at offset 0x16 of the psp */
  1867.     ppid = *(unsigned DFAR *) MK_FP(pid, 0x16);
  1868.  
  1869.     /* find the environment at offset 2Ch of the psp */
  1870.     envsegptr = (unsigned DFAR *) MK_FP(pid, 0x2C);
  1871.     envptr = (char DFAR *) MK_FP(*envsegptr, 0);
  1872.  
  1873.     /*
  1874.      * Make a pointer that contains the size of the environment block.
  1875.      * Must point back one paragraph (to the environments MCB plus three
  1876.      * bytes forward (to the MCB block size field).
  1877.      */
  1878.     envsizeptr = (unsigned DFAR *) MK_FP(*envsegptr - 1, 0x3);
  1879.     envsize = *envsizeptr * 16;    /* x 16 turns it into bytes */
  1880.  
  1881.     while (envsize > 0) {
  1882.         /* search for end of environment block, or NULL */
  1883.         while (--envsize && *envptr++);
  1884.  
  1885.         /*
  1886.          * Now check for another NULL immediately following the first
  1887.          * one located and a word count of 0001 following that.
  1888.          */
  1889.         if (!*envptr && *(unsigned DFAR *) (envptr + 1) == 0x1) {
  1890.             envptr += 3;
  1891.             break;
  1892.         }
  1893.     }
  1894.  
  1895.     if (envsize > 0) {
  1896.         /* Owner name found - return it */
  1897.         return (localcopy(envptr));
  1898.     } else {
  1899.         if (pid == ppid) {
  1900.             /*
  1901.              * command.com doesn't leave it's name around, but if
  1902.              * pid = ppid then we know we have a shell
  1903.              */
  1904.             return ("-shell-");
  1905.         } else {
  1906.             return ("unknown");
  1907.         }
  1908.     }
  1909. }
  1910.  
  1911. #endif /*__TURBOC__*/
  1912.  
  1913.  
  1914.  
  1915. /* Command history, see also pc.c - WG7J */
  1916. void logcmd(cmd)
  1917. char *cmd;
  1918. {
  1919.     struct hist *new;
  1920.     char *cp;
  1921.  
  1922.     if(!Maxhistory)     /* don't keep history */
  1923.         return;
  1924.  
  1925.     /* Get rid of \n; this is also done in cmdparse().
  1926.      * We HAVE to do this here, since the string is NOT null-terminated when
  1927.      * it comes from recv_mbuf()  !!!! rip() makes it nullterminated.
  1928.      */
  1929.     rip(cmd);
  1930.     cp = cmd;
  1931.     while(*cp == ' ' || *cp == '\t')
  1932.         cp++;
  1933.     if(!*cp)     /* Empty command */
  1934.         return;
  1935.  
  1936.     if(Histrysize < Maxhistory) {     /* Add new one */
  1937.         Histrysize++;
  1938.         if(!Histry) {           /* Empty list */
  1939.             /* Initialize circular linked list */
  1940.             Histry = mallocw(sizeof(struct hist));
  1941.             Histry->next = Histry->prev = Histry;
  1942.         } else {
  1943.             new = mallocw(sizeof(struct hist));
  1944.             /* Now link it in */
  1945.             Histry->next->prev = new;
  1946.             new->next = Histry->next;
  1947.             new->prev = Histry;
  1948.             Histry->next = new;
  1949.             Histry = new;
  1950.         }
  1951.     } else {
  1952.         /* Maximum number stored already, use the oldest entry */
  1953.         Histry = Histry->next;
  1954.         free(Histry->cmd);
  1955.     }
  1956.     Histry->cmd = strdup(cp);
  1957. }
  1958.  
  1959. static void freehistory ()
  1960. {
  1961. struct hist *h, *last;
  1962.  
  1963.     if((h = Histry) == NULL)
  1964.         return;
  1965.     do {
  1966.         free (h->cmd);
  1967.         last = h;
  1968.         h = h->prev;
  1969.         free (last);
  1970.     } while(h != Histry);
  1971.     Histry = NULL;
  1972.         Histrysize = 0;
  1973. }
  1974.  
  1975. int
  1976. dohistory(argc,argv,p)
  1977. int argc;
  1978. char *argv[];
  1979. void *p;
  1980. {
  1981.     struct hist *h;
  1982.     int num;
  1983.  
  1984.     if(argc > 1) {
  1985.         Maxhistory = atoi(argv[1]);
  1986.         freehistory ();
  1987.         return 0;
  1988.     }
  1989.     tprintf("Max recall %d\n",Maxhistory);
  1990.     if((h = Histry) == NULL)
  1991.         return 0;
  1992.     num = 0;
  1993.     do {
  1994.         tprintf("%.2d: %s\n",num++,h->cmd);
  1995.         h = h->prev;
  1996.     } while(h != Histry);
  1997.     return 0;
  1998. }
  1999.  
  2000.  
  2001. #if 0
  2002. #ifndef LINUX
  2003.  
  2004. /* This adds some additional checks to the fopen()
  2005.  * in the Borland C++ Run Time Library.
  2006.  * It fixes problem with users trying to open system devices like
  2007.  * CON, AUX etc and hang a system.
  2008.  * WG7J, 930205
  2009.  */
  2010. #undef fopen
  2011. FILE _FAR *_Cdecl fopen(const char _FAR *__path, const char _FAR *__mode);
  2012.  
  2013. static char *InvalidName[] = {
  2014.     "NUL",
  2015.     "CON",
  2016.     "AUX",
  2017.     "PRN",
  2018.     "LPT1",
  2019.     "LPT2",
  2020.     "LPT3",
  2021.     "COM1",
  2022.     "COM2",
  2023.     "COM3",
  2024.     "COM4",
  2025.     "MOUSE$",
  2026.     "CLOCK$",
  2027.     NULLCHAR,
  2028. };
  2029.  
  2030. #ifndef __TURBOC__
  2031. FILE *newfopen (const char *filename, const char *type) {
  2032.     int i;
  2033.  
  2034.     for(i=0;InvalidName[i] != NULLCHAR;i++)
  2035.     if(stricmp(InvalidName[i],filename) == 0)
  2036.         return NULL;
  2037.  
  2038.     return fopen (filename, type);
  2039. }
  2040. #endif
  2041. #endif /* LINUX */
  2042. #endif
  2043.  
  2044. #if defined(__TURBOC__) && !defined(__BORLANDC__)
  2045. /* N5KNX: TurboC 2.0 lacks _setcursortype(), which we supply here for dorepeat */
  2046. void _setcursortype(style)
  2047. int style;
  2048. {
  2049. /* From TurboC++ conio.h: */
  2050. #define _NOCURSOR      0
  2051. #define _SOLIDCURSOR   1
  2052. #define _NORMALCURSOR  2
  2053.  
  2054. /* Int 0x10 reg cx codes: */
  2055. #define   STD_CURSOR      0x0607
  2056. #define   BLK_CURSOR      0x0006
  2057. #define   NO_CURSOR       0x2607
  2058.  
  2059. union REGS regs;
  2060.  
  2061.  if (style == _NOCURSOR) regs.x.cx = NO_CURSOR;
  2062.  else if (style == _SOLIDCURSOR) regs.x.cx = BLK_CURSOR;
  2063.  else if (style == _NORMALCURSOR) regs.x.cx = STD_CURSOR;
  2064.  else return;
  2065.  regs.x.ax = 0x0100; /* set cursor */
  2066.  int86(0x10, ®s, ®s);
  2067. }
  2068. #endif
  2069.  
  2070. /* Repeat a command - taken from 930104 KA9Q NOS
  2071.    WA3DSP 1/93
  2072. */
  2073. int
  2074. dorepeat(argc,argv,p)
  2075. int argc;
  2076. char *argv[];
  2077. void *p;
  2078. {
  2079.     int32 interval;
  2080.     int ret;
  2081.     struct session *sp;
  2082.  
  2083.     if(isdigit(argv[1][0])){
  2084.     interval = atol(argv[1]);
  2085.     argc--;
  2086.     argv++;
  2087.     } else {
  2088.     interval = MSPTICK;
  2089.     }
  2090.     if((sp = newsession(argv[2],REPEAT,0)) == NULLSESSION){
  2091.     tputs("Too many sessions\n");
  2092.     return 1;
  2093.     }
  2094.     _setcursortype(_NOCURSOR);
  2095.     while(sp==Current){
  2096.     /*  clrscr(); */
  2097.     /* gotoxy seems to work better - turn cursor off?? */
  2098.     gotoxy(1,1);
  2099.     ret = subcmd(Cmds,argc,argv,p);
  2100.     if(ret != 0 || mspause(interval) == -1)
  2101.         break;
  2102.     }
  2103.     _setcursortype(_NORMALCURSOR);
  2104.     freesession(sp);
  2105.     return 0;
  2106. }
  2107.  
  2108.  
  2109.